package com.matrix.framework.core.component;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.matrix.framework.core.common.result.Result;
import com.matrix.framework.core.i18n.I18n;
import com.matrix.framework.core.i18n.MessageConstants;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * 自定义认证入口点，处理JWT令牌过期或认证失败的情况
 * 
 * Copyright © 海平面工作室 版权所有
 *
 * @Author: Leo
 * @Create: 2025/06/23 23:25
 * @Since 1.2
 */
@Component
public class MatrixAuthenticationEntryPoint implements ServerAuthenticationEntryPoint {

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException ex) {
        ServerHttpResponse response = exchange.getResponse();
        
        // 设置响应状态和内容类型
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
        
        // 检查是否是JWT相关的错误
        String errorMessage = determineErrorMessage(exchange, ex);
        
        // 创建错误响应
        Result<Object> errorResult = Result.fail()
            .code(HttpStatus.UNAUTHORIZED.value())
            .message(errorMessage);
        
        try {
            // 将错误响应转换为JSON
            String jsonResponse = objectMapper.writeValueAsString(errorResult);
            DataBuffer buffer = response.bufferFactory().wrap(jsonResponse.getBytes(StandardCharsets.UTF_8));
            
            return response.writeWith(Mono.just(buffer));
        } catch (JsonProcessingException e) {
            // 如果JSON序列化失败，返回简单的错误响应
            String fallbackResponse = "{\"code\":401,\"message\":\"" + errorMessage + "\",\"success\":false}";
            DataBuffer buffer = response.bufferFactory().wrap(fallbackResponse.getBytes(StandardCharsets.UTF_8));
            return response.writeWith(Mono.just(buffer));
        }
    }
    
    /**
     * 根据请求上下文确定错误消息
     */
    private String determineErrorMessage(ServerWebExchange exchange, AuthenticationException ex) {
        String authHeader = exchange.getRequest().getHeaders().getFirst("Authorization");
        
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            // 没有提供认证令牌
            return I18n.getMessage(MessageConstants.AUTH_NOT_LOGIN);
        }
        
        // 有认证令牌但验证失败，可能是过期或无效
        try {
            String token = authHeader.substring(7);
            if (!token.isEmpty()) {
                // 尝试解析token来确定具体错误
                return I18n.getMessage(MessageConstants.AUTH_TOKEN_EXPIRED_OR_INVALID);
            }
        } catch (Exception e) {
            // token格式错误
            return I18n.getMessage(MessageConstants.AUTH_TOKEN_INVALID_FORMAT);
        }
        
        return I18n.getMessage(MessageConstants.AUTH_NOT_LOGIN);
    }
} 